package com.example.service.impl;

import com.example.common.Result;
import com.example.entity.User;
import com.example.mapper.UserMapper;
import com.example.service.EmailService;
import com.example.service.EmailVerificationService;
import com.example.service.SystemConfigService;
import com.example.util.RedisUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

/**
 * 邮箱验证服务实现类
 */
@Slf4j
@Service
public class EmailVerificationServiceImpl implements EmailVerificationService {
    
    @Autowired
    private EmailService emailService;
    
    @Autowired
    private SystemConfigService systemConfigService;
    
    @Autowired
    private UserMapper userMapper;
    
    @Autowired
    private RedisUtil redisUtil;
    
    private static final String REGISTER_CODE_PREFIX = "email:register:code:";
    private static final String LOGIN_CODE_PREFIX = "email:login:code:";
    private static final String SEND_LIMIT_PREFIX = "email:send:limit:";
    
    @Override
    public Result<Void> sendRegisterCode(String email) {
        // 检查邮箱注册功能是否启用
        if (!systemConfigService.isEmailRegisterEnabled()) {
            return Result.error("邮箱注册功能未启用");
        }
        
        // 验证邮箱格式
        if (!emailService.isValidEmail(email)) {
            return Result.error("邮箱格式不正确");
        }
        
        // 检查邮箱是否已注册
        if (isEmailRegistered(email)) {
            return Result.error("该邮箱已注册");
        }
        
        // 检查发送频率限制
        if (isRateLimited(email, "register")) {
            return Result.error("发送过于频繁，请稍后再试");
        }
        
        // 生成验证码
        String code = emailService.generateVerificationCode();
        
        // 发送邮件
        boolean sent = emailService.sendVerificationCode(email, code, "register");
        if (!sent) {
            return Result.error("验证码发送失败，请稍后重试");
        }
        
        // 保存验证码到Redis
        int expireTime = systemConfigService.getIntConfig("email.code.expire", 300);
        redisUtil.set(REGISTER_CODE_PREFIX + email, code, expireTime);
        
        // 设置发送频率限制（60秒内不能重复发送）
        redisUtil.set(SEND_LIMIT_PREFIX + email + ":register", "1", 60);
        
        log.info("注册验证码发送成功: email={}", email);
        return Result.success();
    }
    
    @Override
    public Result<Void> sendLoginCode(String email) {
        // 检查邮箱登录功能是否启用
        if (!systemConfigService.isEmailLoginEnabled()) {
            return Result.error("邮箱登录功能未启用");
        }
        
        // 验证邮箱格式
        if (!emailService.isValidEmail(email)) {
            return Result.error("邮箱格式不正确");
        }
        
        // 检查邮箱是否已注册
        if (!isEmailRegistered(email)) {
            return Result.error("该邮箱未注册");
        }
        
        // 检查发送频率限制
        if (isRateLimited(email, "login")) {
            return Result.error("发送过于频繁，请稍后再试");
        }
        
        // 生成验证码
        String code = emailService.generateVerificationCode();
        
        // 发送邮件
        boolean sent = emailService.sendVerificationCode(email, code, "login");
        if (!sent) {
            return Result.error("验证码发送失败，请稍后重试");
        }
        
        // 保存验证码到Redis
        int expireTime = systemConfigService.getIntConfig("email.code.expire", 300);
        redisUtil.set(LOGIN_CODE_PREFIX + email, code, expireTime);
        
        // 设置发送频率限制（60秒内不能重复发送）
        redisUtil.set(SEND_LIMIT_PREFIX + email + ":login", "1", 60);
        
        log.info("登录验证码发送成功: email={}", email);
        return Result.success();
    }
    
    @Override
    public Result<Void> verifyRegisterCode(String email, String code) {
        if (!systemConfigService.isEmailRegisterEnabled()) {
            return Result.error("邮箱注册功能未启用");
        }
        
        String savedCode = (String) redisUtil.get(REGISTER_CODE_PREFIX + email);
        if (savedCode == null) {
            return Result.error("验证码已过期或不存在");
        }
        
        if (!savedCode.equals(code)) {
            return Result.error("验证码错误");
        }
        
        // 验证成功后清除验证码
        clearVerificationCode(email, "register");
        
        log.info("注册验证码验证成功: email={}", email);
        return Result.success();
    }
    
    @Override
    public Result<Void> verifyLoginCode(String email, String code) {
        if (!systemConfigService.isEmailLoginEnabled()) {
            return Result.error("邮箱登录功能未启用");
        }
        
        String savedCode = (String) redisUtil.get(LOGIN_CODE_PREFIX + email);
        if (savedCode == null) {
            return Result.error("验证码已过期或不存在");
        }
        
        if (!savedCode.equals(code)) {
            return Result.error("验证码错误");
        }
        
        // 验证成功后清除验证码
        clearVerificationCode(email, "login");
        
        log.info("登录验证码验证成功: email={}", email);
        return Result.success();
    }
    
    @Override
    public boolean isEmailRegistered(String email) {
        try {
            User user = userMapper.selectByEmail(email);
            return user != null;
        } catch (Exception e) {
            log.error("检查邮箱是否注册失败: email={}", email, e);
            return false;
        }
    }
    
    @Override
    public void clearVerificationCode(String email, String type) {
        String prefix = "register".equals(type) ? REGISTER_CODE_PREFIX : LOGIN_CODE_PREFIX;
        redisUtil.del(prefix + email);
    }
    
    /**
     * 检查发送频率限制
     */
    private boolean isRateLimited(String email, String type) {
        String key = SEND_LIMIT_PREFIX + email + ":" + type;
        return redisUtil.hasKey(key);
    }
}
